

package com.googlecode.flac4j.format.frame.sub;


import com.googlecode.jinahya.io.BitInput;
import com.googlecode.jinahya.io.BitOutput;

import java.io.IOException;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlType;


/**
 *
 * @author Jin Kwon <jinahya at gmail.com>
 */
@XmlType(propOrder = {"samples", "residual"})
public class FIXED extends AbstractSubData {


    public FIXED() {
        super(0x08, 3);
    }


    @Override
    public void read(final BitInput input) throws IOException {

        final int bitsPerSample = getFrameHeader().getSampleSize();
        samples.clear();
        final int order = getOrder();
        for (int i = 0; i < order; i++) {
            samples.add(input.readUnsignedInt(bitsPerSample));
        }

        getResidual().read(input);
    }


    @Override
    public void write(final BitOutput output) throws IOException {

        final int bitsPerSample = getFrameHeader().getSampleSize();
        final int order = getOrder();
        if (samples.size() != order) {
            throw new IllegalStateException(
                "samples.size(" + samples.size() + ") != order(" + order + ")");
        }
        for (int sample : samples) {
            output.writeUnsignedInt(bitsPerSample, sample);
        }

        getResidual().write(output);
    }


    // ----------------------------------------------------------------- samples
    /**
     * Clears samples.
     */
    public void clearSamples() {
        samples.clear();
    }


    /**
     * Returns the number of samples added so far.
     *
     * @return the number of samples
     */
    public int getSampleCount() {
        return samples.size();
    }


    /**
     * Adds given <code>sample</code> to the list.
     *
     * @param sample sample to add
     */
    public void addSample(final int sample) {

        final int bitsPerSample = getFrameHeader().getSampleSize();

        if (sample >> bitsPerSample != 0) {
            throw new IllegalArgumentException(
                "sample(" + sample + ") >> bitsPerSample(" + bitsPerSample
                + ") != 0)");
        }

        samples.add(sample);
    }


    // ---------------------------------------------------------------- residual
    /**
     * Returns residual.
     *
     * @return residual
     */
    public Residual getResidual() {

        if (residual == null) {
            residual = new Residual();
        }

        return residual;
    }


    @XmlElement(name = "sample")
    @XmlElementWrapper(required = true)
    private final List<Integer> samples = new ArrayList<Integer>();


    @XmlElement(required = true)
    private Residual residual;


}

